package cn.biplam.back.bean.tree;

import java.io.Serializable;
import java.util.ArrayList;

import cn.biplam.back.sql.select.BaseSelect;
import cn.biplam.common.bean.sqlengine.Sql;
import cn.biplam.common.bean.tree.TreeParentData;
import cn.biplam.common.bean.tree.TreeParentDataMap;
import cn.biplam.common.client.Database;
import cn.biplam.common.client.DbResource;
import cn.biplam.common.paramters.SysName;
import cn.biplam.common.paramters.SelectConstant.Operator_Rela;
import cn.biplam.common.paramters.TreeParam.DataType;
import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.sqlresult.SqlResult;

/**
 * 父子树数据集生成
 * @author WangSong 2009-11-4下午02:18:33
 * @version 1.0
 */
public class TreeParentDataImp extends TreeParentData implements Serializable {
	/** */
	private static final long serialVersionUID = 4720729022014260573L;
	private DbResource dbResource;
	/** 查询结果集*/
	private ArrayList<SqlResult> arNodeList;
	private BaseSql baseSql;
	private String tableName;
	private TreeParentDataMap fieldMap;
	private int level=1;

	protected TreeParentDataImp(){
		this.arNodeList=new ArrayList<SqlResult>();
	}

	/**
	 * 构造方法
	 * @param dbResource	数据源(指定查询请求的数据源)
	 * @param tableName		树形表名称
	 * @param keyField		主键字段名称
	 * @param parentField	上级字段名称
	 * @param keyID			开始节点的主键ID
	 * @throws ErrorMessage 
	 */
	public TreeParentDataImp(DbResource dbResource,String tableName,TreeParentDataMap fieldMap,String keyID) throws ErrorMessage{
		this();
		this.dbResource=dbResource;
		this.baseSql=new BaseSql(tableName,fieldMap);
		this.baseSql.putStringFilter(fieldMap.getNodeParent(), keyID,Operator_Rela.E);
		this.tableName = tableName;
		this.fieldMap = fieldMap;
	}
	
	/**
	 * 设置树的节点级别
	 * @param level
	 */
	public void setLevel(int level){
		this.level = level;
	}
	
	/**
	 * 放入一个字符类型过滤条件
	 * @param filterFieldName	过滤字段名
	 * @param filterValue		过滤值
	 * @param rela 比较符常量
	 * @throws ErrorMessage
	 */
	public void putStringFilter(String filterFieldName,String filterValue,Operator_Rela rela) throws ErrorMessage{
		this.baseSql.putStringFilter(filterFieldName, filterValue,rela);
	}
	
	/**
	 * 放入一个数字类型过滤条件
	 * @param filterFieldName	过滤字段名
	 * @param filterValue		过滤值
	 * @param rela 比较符常量
	 * @throws ErrorMessage
	 */
	public void putNumFilter(String filterFieldName,String filterValue,Operator_Rela rela) throws ErrorMessage{
		this.baseSql.putNumFilter(filterFieldName, filterValue,rela);
	}


	/**
	 * 返回下级节点的SqlResult
	 * @return	SqlResult
	 * @throws ErrorMessage 
	 */
	public SqlResult getReslut() throws ErrorMessage{
		SqlResult sr = null;
		for(SqlResult rs:this.arNodeList){
			if(sr == null){
				sr = rs;
			}else{
				sr.concat(rs);
			}
		}
	
		return sr;
	}
	
	/* (non-Javadoc)
	 * @see cn.biplam.front.component.data.tree.treebase.parent.TreeParentData#start()
	 */
	public void start() throws ErrorMessage{
		/**查找直接下级*/
		Database db = new Database(this.dbResource,SysName.SysUser,null);
		this.find(db,this.level);
	}

	/**
	 * 递归查找
	 * @param db		创建好的数据源
	 * @param baseSql	查询下级节点的基础SQL(使用时附加上keyID)
	 * @param keyId		主键字段ID值
	 * @throws ErrorMessage 
	 */
	protected void find(Database db,int level) throws ErrorMessage{
		this.baseSql.setLevel(level);
		SqlResult rs = db.executeSelect(new Sql(baseSql.toString()));
		if(TOOLS.exist(rs)){
			this.arNodeList.add(rs);
		}
		
		while(rs.next()){
			String curKeyID=rs.get(rs.getCurrentRow(), 0);
			TreeParentDataImp next=new TreeParentDataImp(dbResource,tableName,fieldMap,curKeyID);
			next.find(db,level+1);
			this.addChildNode(next.getNodeList());
		}
	}
	
	/**
	 * 增加下级节点列表(用于递归时返回数据)
	 * @param list
	 * @throws ErrorMessage 
	 */
	protected void addChildNode(ArrayList<SqlResult> list) throws ErrorMessage{
		if(list!=null)
			this.arNodeList.addAll(list);
	}
	
	/* (non-Javadoc)
	 * @see cn.biplam.front.component.data.tree.treebase.parent.TreeParentData#getNodeList()
	 */
	public ArrayList<SqlResult> getNodeList(){
		return this.arNodeList;
	}
	
	/**
	 * 递归时使用的基础Sql参数<BR>
	 * 为支持用多个过滤参数生成每次递归查询所需Sql而创建<BR>
	 * 为对查询结果的过滤提供处理方法,因为过滤字段存在本类中
	 */
	public class BaseSql implements Serializable {
		
		/** */
		private static final long serialVersionUID = 4944161720990298069L;
		BaseSelect select;
		KvMap<String, DataType> filterFields=new KvMap<String, DataType>();
		KvMap<String, String> filterValues=new KvMap<String, String>();

		/**
		 * 1.创建基本字段列表部分
		 * 2.格式化存储过滤条件部分,记录过滤条件的类型(字符型/数字型)
		 * 3.每次使用时,传入SqlResult,按预存的过滤字段名称和类型取值,赋值,组装出完整的Sql
		 * @throws ErrorMessage 
		 * */
		public BaseSql(String tableName,TreeParentDataMap filedMap) throws ErrorMessage{
			this.select=new BaseSelect(tableName);
			this.select.putField(filedMap.getNodeId());
			this.select.putField(filedMap.getNodeName());
			this.select.putField(filedMap.getNodeParent());
			this.select.putField(filedMap.getRealId());
			if("d_operator_type".equals(filedMap.getOperatorType())){
				this.select.putField("'1' as d_operator_type");
			}else{
				this.select.putField(filedMap.getOperatorType());
			}
			this.select.putField("'1' as node_type");
			
			this.filterFields.put(filedMap.getNodeParent(), DataType.Str);
		}
		
		/**
		 * 设置级别信息
		 * @param level
		 */
		public void setLevel(int level){
			this.select.putField("'"+level+"' as nodel_level");
		}
		
		/**
		 * 按类型储存过滤参数到BaseSelect(类型决定是否加单引号)
		 */
		private void _putFilterValue(String filterFieldName,String filterValue,DataType type,Operator_Rela rela) throws ErrorMessage{
			switch(type){
			case Str:
				this.select.putStringFilter(filterFieldName, filterValue,rela);
				break;
			case Num:
				this.select.putNumberFilter(filterFieldName, TOOLS.stringToInt(filterValue),rela);
			}
		}

		/**
		 * 放入一个字符过滤条件
		 */
		public void putStringFilter(String filterFieldName,String filterValue,Operator_Rela rela) throws ErrorMessage{
			this.filterFields.put(filterFieldName, DataType.Str);//存储字段类型,在rs赋值时使用
			this._putFilterValue(filterFieldName, filterValue,DataType.Str,rela);
		}
		
		/**
		 * 放入一个数字过滤条件
		 */
		public void putNumFilter(String filterFieldName,String filterValue,Operator_Rela rela) throws ErrorMessage{
			this.filterFields.put(filterFieldName, DataType.Num);//存储字段类型,在rs赋值时使用
			this._putFilterValue(filterFieldName, filterValue,DataType.Num,rela);
		}
		
		/**
		 * 返回标准sql表达式
		 * @return	String
		 */
		@Override	
		public String toString(){
			return this.select.toString();
		}
	}
}
